import javax.swing.*;
import javax.swing.border.LineBorder;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class NormalGrammarPage {
    JPanel PagePanel;
    JMenuBar MenuBar;
    //输入框
    JTextField textField;
    //按钮
    JButton button_check;
    JButton button_run;
    JButton button_fresh;
    //文本域
    JTextArea leftTA = new JTextArea();
    JTextArea rightTA = new JTextArea();
    JTextArea midTA = new JTextArea();

    //显示标签
    JLabel s1;
    JLabel s2;
    JLabel s3;
    JLabel e1;
    JLabel e2;
    JLabel e3;

    public NormalGrammarPage(){
        PagePanel = new JPanel();
        PagePanel.setBounds(0,0,1280,720);
        PagePanel.setLayout(null);
        // 初始化菜单栏
        createMenuBar();
        // 创建基本的UI组件
        this.CreateUI();

    }

    private void CreateUI() {

        //上方输入框面板
        JPanel topPanel = new JPanel();
        topPanel.setLayout(null);
        topPanel.setBounds(0,0,1280,60);
        topPanel.setBorder(new LineBorder(Color.BLUE,2));
        PagePanel.add(topPanel);
        //第一面板
        JPanel Panel1 = new JPanel();
        Panel1.setLayout(null);
        Panel1.setBounds(20,70,400,580);
        Panel1.setBorder(new LineBorder(Color.cyan,2));
        PagePanel.add(Panel1);
        //第二面板
        JPanel Panel2 = new JPanel();
        Panel2.setLayout(null);
        Panel2.setBounds(433,70,400,580);
        Panel2.setBorder(new LineBorder(Color.cyan,2));
        PagePanel.add(Panel2);
        //第三面板
        JPanel Panel3 = new JPanel();
        Panel3.setLayout(null);
        Panel3.setBounds(846,70,400,580);
        Panel3.setBorder(new LineBorder(Color.cyan,2));
        PagePanel.add(Panel3);
        //上面板
        JLabel label1 = new JLabel("输入正规表达式：");
        label1.setBounds(50,10,100,30);
        topPanel.add(label1);
        this.textField = new JTextField();
        this.textField.setBounds(160,10,380,30);
        topPanel.add(this.textField);
        button_check = new JButton("检查正规式");
        button_check.setBounds(560,10,100,40);
        topPanel.add(button_check);
        button_run = new JButton("分析开始");
        button_run.setBounds(680,10,100,40);
        topPanel.add(button_run);
        button_run.setEnabled(false);
        JLabel label5 = new JLabel("正规表达式即^d{n,}$ ^d{n}$ ^(-)?d+(.d{1,2})?$ 类似的");
        label5.setBounds(800,10,400,30);
        topPanel.add(label5);
        button_fresh = new JButton("清空重载");
        button_fresh.setBounds(1150,10,100,40);
        topPanel.add(button_fresh);

        LineBorder GrayBorder = new LineBorder(Color.GRAY,2);
        //左面板
        JLabel label2 = new JLabel("正规式-->>NFA");
        label2.setBounds(5,10,100,30);
        Panel1.add(label2);
        JLabel leftL1 = new JLabel("起始状态");
        leftL1.setBounds(5,35,130,30);
        leftL1.setBorder(GrayBorder);
        Panel1.add(leftL1);
        JLabel leftL2 = new JLabel("接收符号");
        leftL2.setBounds(135,35,130,30);
        leftL2.setBorder(GrayBorder);
        Panel1.add(leftL2);
        JLabel leftL3 = new JLabel("结束状态");
        leftL3.setBounds(265,35,130,30);
        leftL3.setBorder(GrayBorder);
        Panel1.add(leftL3);


        leftTA.setEditable(false);
        JScrollPane leftScrollPane = new JScrollPane(leftTA);
        leftScrollPane.setBounds(10, 70, 380, 400);
        Panel1.add(leftScrollPane);

        s1 = new JLabel("开始状态集：");
        s1.setBounds(10,480,130,30);
        Panel1.add(s1);
        e1 = new JLabel("结束状态集：");
        e1.setBounds(200,480,130,30);
        Panel1.add(e1);

        // 添加保存按钮
        JButton saveNFAButton = new JButton("保存NFA");
        saveNFAButton.setBounds(150, 540, 100, 30);
        Panel1.add(saveNFAButton);
        saveNFAButton.addActionListener(e -> saveTransitionTable(leftTA.getText(), "NFA状态转移表"));

        //中面板
        JLabel label3 = new JLabel("NFA-->>DFA");
        label3.setBounds(5,10,100,30);
        Panel2.add(label3);
        JLabel midL1 = new JLabel("起始状态");
        midL1.setBounds(5,35,130,30);
        midL1.setBorder(GrayBorder);
        Panel2.add(midL1);
        JLabel midL2 = new JLabel("接收符号");
        midL2.setBounds(135,35,130,30);
        midL2.setBorder(GrayBorder);
        Panel2.add(midL2);
        JLabel midL3 = new JLabel("结束状态");
        midL3.setBounds(265,35,130,30);
        midL3.setBorder(GrayBorder);
        Panel2.add(midL3);

        midTA.setEditable(false);
        JScrollPane midScrollPane = new JScrollPane(midTA);
        midScrollPane.setBounds(10, 70, 380, 400);
        Panel2.add(midScrollPane);

        s2 = new JLabel("开始状态集：");
        s2.setBounds(10,480,130,30);
        Panel2.add(s2);
        e2 = new JLabel("结束状态集：");
        e2.setBounds(200,480,130,30);
        Panel2.add(e2);

        // 添加保存按钮
        JButton saveDFAButton = new JButton("保存DFA");
        saveDFAButton.setBounds(150, 540, 100, 30);
        Panel2.add(saveDFAButton);
        saveDFAButton.addActionListener(e -> saveTransitionTable(midTA.getText(), "DFA状态转移表"));

        //右面板
        JLabel label4 = new JLabel("DFA-->>MFA");
        label4.setBounds(5,10,100,30);
        Panel3.add(label4);
        JLabel rightL1 = new JLabel("起始状态");
        rightL1.setBounds(5,35,130,30);
        rightL1.setBorder(GrayBorder);
        Panel3.add(rightL1);
        JLabel rightL2 = new JLabel("接收符号");
        rightL2.setBounds(135,35,130,30);
        rightL2.setBorder(GrayBorder);
        Panel3.add(rightL2);
        JLabel rightL3 = new JLabel("结束状态");
        rightL3.setBounds(265,35,130,30);
        rightL3.setBorder(GrayBorder);
        Panel3.add(rightL3);

        rightTA.setEditable(false);
        JScrollPane rightScrollPane = new JScrollPane(rightTA);
        rightScrollPane.setBounds(10, 70, 380, 400);
        Panel3.add(rightScrollPane);

        s3 = new JLabel("开始状态集：");
        s3.setBounds(10,480,130,30);
        Panel3.add(s3);
        e3 = new JLabel("结束状态集：");
        e3.setBounds(200,480,130,30);
        Panel3.add(e3);

        // 添加保存按钮
        JButton saveMFAButton = new JButton("保存MFA");
        saveMFAButton.setBounds(150, 540, 100, 30);
        Panel3.add(saveMFAButton);
        saveMFAButton.addActionListener(e -> saveTransitionTable(rightTA.getText(), "MFA状态转移表"));

        //按钮引用
        //检查是否正则表达式
        button_check.addActionListener(e -> this.CheckRegularExpression());
        //分析开始
        button_run.addActionListener(e -> this.Analyze());
        //重载
        button_fresh.addActionListener(e -> {
            if(JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(PagePanel, "是否重载？", "提示", JOptionPane.YES_NO_OPTION)){
                this.Fresh();
            }
        });
    }

    //分析总功能
    private void Analyze(){
        this.RegularExpressionToNFA();
        this.NFAtoDFA();
        this.DFAtoMFA();
    }
    //正则变NFA
    private void RegularExpressionToNFA(){
        String regex = textField.getText();
        StringBuilder nfaResult = new StringBuilder();
        // 构建NFA表格显示
        NFA nfa = buildNFA(regex);
        for (NFA.Transition t : nfa.transitions) {
            nfaResult.append(String.format("%10s%35s%35s\n", t.from, t.symbol, t.to));
        }
        leftTA.setText(nfaResult.toString());

        // 显示开始状态集和结束状态集
        Component[] components = PagePanel.getComponents();
        for (Component comp : components) {
            if (comp instanceof JPanel) {
                JPanel panel = (JPanel) comp;
                if (panel.getBounds().x == 20 && panel.getBounds().y == 70) { // 左侧面板
                    Component[] panelComponents = panel.getComponents();
                    for (Component panelComp : panelComponents) {
                        if (panelComp instanceof JLabel) {
                            JLabel label = (JLabel) panelComp;
                            if (label.getText().equals("开始状态集：")) {
                                label.setText("开始状态集：" + nfa.startState);
                                label.setForeground(Color.BLUE);
                            } else if (label.getText().equals("结束状态集：")) {
                                label.setText("结束状态集：" + nfa.finalStates);
                                label.setForeground(Color.BLUE);
                            }
                        }
                    }
                }
            }
        }
    }

    // 构建NFA的核心方法
    private NFA buildNFA(String regex) {
        if (regex == null || regex.isEmpty()) {
            return new NFA();
        }

        Stack<NFA> nfaStack = new Stack<>();
        Stack<Character> operatorStack = new Stack<>();

        int stateCounter = 0;

        for (int i = 0; i < regex.length(); i++) {
            char c = regex.charAt(i);

            if (c == '(') {
                operatorStack.push(c);
            } else if (c == ')') {
                while (!operatorStack.isEmpty() && operatorStack.peek() != '(') {
                    processOperator(nfaStack, operatorStack.pop(), stateCounter);
                    // 更新状态计数器
                    stateCounter += 2;
                }
                if (!operatorStack.isEmpty()) {
                    operatorStack.pop(); // 弹出 '('
                }
            } else if (c == '*') {
                // 克林闭包操作具有最高优先级
                if (!nfaStack.isEmpty()) {
                    NFA top = nfaStack.pop();
                    NFA closureNFA = createClosureNFA(top, stateCounter);
                    stateCounter += 2; // 新增两个状态
                    nfaStack.push(closureNFA);
                }
            } else if (c == '|') {
                // 处理之前的操作符（优先处理连接操作）
                while (!operatorStack.isEmpty() && operatorStack.peek() != '(') {
                    processOperator(nfaStack, operatorStack.pop(), stateCounter);
                    // 更新状态计数器
                    stateCounter += 2;
                }
                operatorStack.push(c);
            } else {
                // 普通字符，创建单字符NFA
                NFA charNFA = createCharNFA(c, stateCounter);
                stateCounter += 2; // 每个字符NFA需要两个新状态
                nfaStack.push(charNFA);

                // 处理连接操作（隐式操作符）
                while (i + 1 < regex.length() &&
                       (regex.charAt(i + 1) == '(' ||
                        regex.charAt(i + 1) != '|' &&
                        regex.charAt(i + 1) != ')' &&
                        regex.charAt(i + 1) != '*')) {

                    // 如果下一个字符是普通字符，需要处理连接操作
                    if (i + 1 < regex.length() &&
                        regex.charAt(i + 1) != '|' &&
                        regex.charAt(i + 1) != '(' &&
                        regex.charAt(i + 1) != ')' &&
                        regex.charAt(i + 1) != '*') {

                        operatorStack.push('.'); // 连接操作符
                    }
                    break;
                }
            }
        }

        // 处理剩余的操作符
        while (!operatorStack.isEmpty()) {
            processOperator(nfaStack, operatorStack.pop(), stateCounter);
            stateCounter += 2;
        }

        // 最终的NFA应该是栈中唯一的元素
        if (!nfaStack.isEmpty()) {
            return nfaStack.pop();
        } else {
            return new NFA();
        }
    }

    // 处理操作符
    private void processOperator(Stack<NFA> nfaStack, char operator, int stateCounter) {
        switch (operator) {
            case '|': // 或操作
                if (nfaStack.size() >= 2) {
                    NFA nfa2 = nfaStack.pop();
                    NFA nfa1 = nfaStack.pop();
                    NFA unionNFA = createUnionNFA(nfa1, nfa2, stateCounter);
                    nfaStack.push(unionNFA);
                }
                break;
            case '.': // 连接操作
                if (nfaStack.size() >= 2) {
                    NFA nfa2 = nfaStack.pop();
                    NFA nfa1 = nfaStack.pop();
                    NFA concatNFA = createConcatenationNFA(nfa1, nfa2);
                    nfaStack.push(concatNFA);
                }
                break;
        }
    }

    // 创建单字符NFA
    private NFA createCharNFA(char symbol, int stateCounter) {
        NFA nfa = new NFA();
        int endState = stateCounter + 1;

        nfa.transitions.add(new NFA.Transition(stateCounter, String.valueOf(symbol), endState));
        nfa.startState = stateCounter;
        nfa.finalStates.add(endState);

        return nfa;
    }

    // 创建连接NFA (nfa1后跟nfa2)
    private NFA createConcatenationNFA(NFA nfa1, NFA nfa2) {
        NFA nfa = new NFA();

        // 添加两个NFA的所有转换
        nfa.transitions.addAll(nfa1.transitions);
        nfa.transitions.addAll(nfa2.transitions);

        // 连接nfa1的终态到nfa2的初态（通过ε转换）
        for (int finalState : nfa1.finalStates) {
            nfa.transitions.add(new NFA.Transition(finalState, "#", nfa2.startState));
        }

        // 设置新NFA的初态和终态
        nfa.startState = nfa1.startState;
        nfa.finalStates.addAll(nfa2.finalStates);

        return nfa;
    }

    // 创建或操作NFA (nfa1|nfa2)
    private NFA createUnionNFA(NFA nfa1, NFA nfa2, int stateCounter) {
        NFA nfa = new NFA();
        int newEndState = stateCounter + 1;

        // 添加ε转换从新初态到两个子NFA的初态
        nfa.transitions.add(new NFA.Transition(stateCounter, "#", nfa1.startState));
        nfa.transitions.add(new NFA.Transition(stateCounter, "#", nfa2.startState));

        // 添加两个子NFA的所有转换
        nfa.transitions.addAll(nfa1.transitions);
        nfa.transitions.addAll(nfa2.transitions);

        // 添加ε转换从两个子NFA的终态到新终态
        for (int finalState : nfa1.finalStates) {
            nfa.transitions.add(new NFA.Transition(finalState, "#", newEndState));
        }
        for (int finalState : nfa2.finalStates) {
            nfa.transitions.add(new NFA.Transition(finalState, "#", newEndState));
        }

        // 设置新NFA的初态和终态
        nfa.startState = stateCounter;
        nfa.finalStates.add(newEndState);

        return nfa;
    }

    // 创建克林闭包NFA
    private NFA createClosureNFA(NFA subNFA, int stateCounter) {
        NFA nfa = new NFA();
        int newEndState = stateCounter + 1;

        // 添加ε转换从新初态到原子NFA的初态
        nfa.transitions.add(new NFA.Transition(stateCounter, "#", subNFA.startState));
        // 添加ε转换从新初态到新终态（表示0次匹配）
        nfa.transitions.add(new NFA.Transition(stateCounter, "#", newEndState));

        // 添加原子NFA的所有转换
        nfa.transitions.addAll(subNFA.transitions);

        // 添加ε转换从原子NFA的终态到新终态
        for (int finalState : subNFA.finalStates) {
            nfa.transitions.add(new NFA.Transition(finalState, "#", newEndState));
            // 添加ε转换从原子NFA的终态回到其初态（表示多次匹配）
            nfa.transitions.add(new NFA.Transition(finalState, "#", subNFA.startState));
        }

        // 设置新NFA的初态和终态
        nfa.startState = stateCounter;
        nfa.finalStates.add(newEndState);

        return nfa;
    }

    //NFA变DFA
    private void NFAtoDFA(){
        String regex = textField.getText();
        NFA nfa = buildNFA(regex);
        DFA dfa = convertNFAtoDFA(nfa);

        StringBuilder dfaResult = new StringBuilder();
        // 显示DFA转换结果，按照要求格式化输出
        List<String> startStates = new ArrayList<>();
        List<String> symbols = new ArrayList<>();
        List<String> endStates = new ArrayList<>();

        for (Map.Entry<DFAState, Map<String, DFAState>> entry : dfa.transitions.entrySet()) {
            DFAState fromState = entry.getKey();
            Map<String, DFAState> transitions = entry.getValue();

            // 按字母顺序处理转换，确保输出顺序一致
            TreeMap<String, DFAState> sortedTransitions = new TreeMap<>(transitions);
            for (Map.Entry<String, DFAState> transEntry : sortedTransitions.entrySet()) {
                String symbol = transEntry.getKey();
                DFAState toState = transEntry.getValue();

                startStates.add(String.valueOf(fromState.id));
                symbols.add(symbol);
                endStates.add(String.valueOf(toState.id));
            }
        }

        // 格式化输出 - 按列显示（竖向显示）
        // 设置固定宽度以确保对齐，第一列前有10个空格间隔，列间距35个字符
        for (int i = 0; i < startStates.size(); i++) {
            dfaResult.append(String.format("%10s%35s%35s\n", startStates.get(i), symbols.get(i), endStates.get(i)));
        }

        midTA.setText(dfaResult.toString());

        // 显示开始状态集和结束状态集
        Set<Integer> dfaStartStates = new HashSet<>();
        Set<Integer> dfaFinalStates = new HashSet<>();
        dfaStartStates.add(dfa.startState.id);
        for (DFAState state : dfa.finalStates) {
            dfaFinalStates.add(state.id);
        }

        Component[] components = PagePanel.getComponents();
        for (Component comp : components) {
            if (comp instanceof JPanel) {
                JPanel panel = (JPanel) comp;
                if (panel.getBounds().x == 433 && panel.getBounds().y == 70) { // 中面板
                    Component[] panelComponents = panel.getComponents();
                    for (Component panelComp : panelComponents) {
                        if (panelComp instanceof JLabel) {
                            JLabel label = (JLabel) panelComp;
                            if (label.getText().equals("开始状态集：")) {
                                label.setText("开始状态集：" + dfaStartStates);
                                label.setForeground(Color.BLUE);
                            } else if (label.getText().equals("结束状态集：")) {
                                label.setText("结束状态集：" + dfaFinalStates);
                                label.setForeground(Color.BLUE);
                            }
                        }
                    }
                }
            }
        }
    }

    //DFA变MFA
    private void DFAtoMFA(){
        String regex = textField.getText();
        NFA nfa = buildNFA(regex);
        DFA dfa = convertNFAtoDFA(nfa);
        DFA minDFA = minimizeDFA(dfa);

        StringBuilder mfaResult = new StringBuilder();
        // 显示最小化DFA转换结果，按照要求格式化输出
        List<String> startStates = new ArrayList<>();
        List<String> symbols = new ArrayList<>();
        List<String> endStates = new ArrayList<>();

        for (Map.Entry<DFAState, Map<String, DFAState>> entry : minDFA.transitions.entrySet()) {
            DFAState fromState = entry.getKey();
            Map<String, DFAState> transitions = entry.getValue();

            // 按字母顺序处理转换，确保输出顺序一致
            TreeMap<String, DFAState> sortedTransitions = new TreeMap<>(transitions);
            for (Map.Entry<String, DFAState> transEntry : sortedTransitions.entrySet()) {
                String symbol = transEntry.getKey();
                DFAState toState = transEntry.getValue();

                startStates.add(String.valueOf(fromState.id));
                symbols.add(symbol);
                endStates.add(String.valueOf(toState.id));
            }
        }

        // 格式化输出 - 按列显示（竖向显示）
        // 设置固定宽度以确保对齐，第一列前有10个空格间隔，列间距35个字符
        for (int i = 0; i < startStates.size(); i++) {
            mfaResult.append(String.format("%10s%35s%35s\n", startStates.get(i), symbols.get(i), endStates.get(i)));
        }

        rightTA.setText(mfaResult.toString());

        // 显示开始状态集和结束状态集
        Set<Integer> minDfaStartStates = new HashSet<>();
        Set<Integer> minDfaFinalStates = new HashSet<>();
        minDfaStartStates.add(minDFA.startState.id);
        for (DFAState state : minDFA.finalStates) {
            minDfaFinalStates.add(state.id);
        }

        Component[] components = PagePanel.getComponents();
        for (Component comp : components) {
            if (comp instanceof JPanel) {
                JPanel panel = (JPanel) comp;
                if (panel.getBounds().x == 846 && panel.getBounds().y == 70) { // 右侧面板
                    Component[] panelComponents = panel.getComponents();
                    for (Component panelComp : panelComponents) {
                        if (panelComp instanceof JLabel) {
                            JLabel label = (JLabel) panelComp;
                            if (label.getText().equals("开始状态集：")) {
                                label.setText("开始状态集：" + minDfaStartStates);
                                label.setForeground(Color.BLUE);
                            } else if (label.getText().equals("结束状态集：")) {
                                label.setText("结束状态集：" + minDfaFinalStates);
                                label.setForeground(Color.BLUE);
                            }
                        }
                    }
                }
            }
        }
    }

    // NFA转DFA的实现（子集构造法）
    private DFA convertNFAtoDFA(NFA nfa) {
        DFA dfa = new DFA();

        // 获取NFA的字母表
        Set<String> alphabet = new HashSet<>();
        for (NFA.Transition t : nfa.transitions) {
            if (!t.symbol.equals("#")) { // 排除ε转换
                alphabet.add(t.symbol);
            }
        }

        // 使用子集构造法
        Queue<Set<Integer>> queue = new LinkedList<>();
        Map<Set<Integer>, DFAState> nfaToDfaStateMap = new HashMap<>();
        int stateIdCounter = 0;

        // 计算初始状态的ε闭包
        Set<Integer> startStateEpsilonClosure = epsilonClosure(nfa, nfa.startState);
        DFAState dfaStartState = new DFAState(stateIdCounter++, startStateEpsilonClosure);
        nfaToDfaStateMap.put(startStateEpsilonClosure, dfaStartState);
        dfa.startState = dfaStartState;
        queue.add(startStateEpsilonClosure);
        dfa.states.add(dfaStartState);

        // 检查初始状态是否包含NFA的终态
        if (containsAny(startStateEpsilonClosure, nfa.finalStates)) {
            dfa.finalStates.add(dfaStartState);
        }

        // 处理队列中的每个状态
        while (!queue.isEmpty()) {
            Set<Integer> nfaStateSet = queue.poll();
            DFAState currentDFAState = nfaToDfaStateMap.get(nfaStateSet);

            // 对于字母表中的每个符号
            for (String symbol : alphabet) {
                // 计算从当前状态通过该符号能到达的状态集合
                Set<Integer> nextStates = new HashSet<>();

                // 对于当前状态集合中的每个状态
                for (Integer state : nfaStateSet) {
                    // 查找通过该符号的转换
                    for (NFA.Transition t : nfa.transitions) {
                        if (t.from == state && t.symbol.equals(symbol)) {
                            nextStates.add(t.to);
                        }
                    }
                }

                // 计算到达状态的ε闭包
                Set<Integer> nextStateEpsilonClosure = new HashSet<>();
                for (Integer state : nextStates) {
                    nextStateEpsilonClosure.addAll(epsilonClosure(nfa, state));
                }

                if (!nextStateEpsilonClosure.isEmpty()) {
                    DFAState nextDFAState;
                    // 如果这是新状态，添加到队列中
                    if (!nfaToDfaStateMap.containsKey(nextStateEpsilonClosure)) {
                        nextDFAState = new DFAState(stateIdCounter++, nextStateEpsilonClosure);
                        nfaToDfaStateMap.put(nextStateEpsilonClosure, nextDFAState);
                        queue.add(nextStateEpsilonClosure);
                        dfa.states.add(nextDFAState);

                        // 检查是否包含NFA的终态
                        if (containsAny(nextStateEpsilonClosure, nfa.finalStates)) {
                            dfa.finalStates.add(nextDFAState);
                        }
                    } else {
                        nextDFAState = nfaToDfaStateMap.get(nextStateEpsilonClosure);
                    }

                    // 添加转换
                    dfa.transitions.computeIfAbsent(currentDFAState, k -> new HashMap<>()).put(symbol, nextDFAState);
                }
            }
        }

        return dfa;
    }

    // 计算状态的ε闭包
    private Set<Integer> epsilonClosure(NFA nfa, int state) {
        Set<Integer> closure = new HashSet<>();
        closure.add(state);
        return epsilonClosure(nfa, closure);
    }

    // 计算状态集合的ε闭包
    private Set<Integer> epsilonClosure(NFA nfa, Set<Integer> states) {
        Set<Integer> closure = new HashSet<>(states);
        Stack<Integer> stack = new Stack<>();
        stack.addAll(states);

        while (!stack.isEmpty()) {
            int currentState = stack.pop();

            // 查找所有ε转换
            for (NFA.Transition t : nfa.transitions) {
                if (t.from == currentState && t.symbol.equals("#") && !closure.contains(t.to)) {
                    closure.add(t.to);
                    stack.push(t.to);
                }
            }
        }

        return closure;
    }

    // 检查两个集合是否有交集
    private boolean containsAny(Set<Integer> set1, Set<Integer> set2) {
        for (Integer element : set1) {
            if (set2.contains(element)) {
                return true;
            }
        }
        return false;
    }

    // 最小化DFA（使用Hopcroft算法的思想）
    private DFA minimizeDFA(DFA dfa) {
        // 初始化：将状态分为接受状态和非接受状态
        Set<DFAState> finalStates = new HashSet<>(dfa.finalStates);
        Set<DFAState> nonFinalStates = dfa.states.stream()
                .filter(s -> !finalStates.contains(s))
                .collect(Collectors.toSet());

        List<Set<DFAState>> partitions = new ArrayList<>();
        if (!nonFinalStates.isEmpty()) {
            partitions.add(nonFinalStates);
        }
        if (!finalStates.isEmpty()) {
            partitions.add(finalStates);
        }

        boolean changed = true;
        while (changed) {
            changed = false;
            List<Set<DFAState>> newPartitions = new ArrayList<>();

            for (Set<DFAState> partition : partitions) {
                // 如果分区只有一个状态，不需要进一步分割
                if (partition.size() <= 1) {
                    newPartitions.add(partition);
                    continue;
                }

                // 尝试根据转移函数分割分区
                Map<String, Set<DFAState>> separationMap = new HashMap<>();

                for (DFAState state : partition) {
                    // 为每个状态创建一个签名，基于其转换
                    StringBuilder signature = new StringBuilder();

                    // 获取所有可能的符号
                    Set<String> symbols = new HashSet<>();
                    for (DFAState s : dfa.states) {
                        if (dfa.transitions.containsKey(s)) {
                            symbols.addAll(dfa.transitions.get(s).keySet());
                        }
                    }

                    // 对每个符号，检查转移到哪个分区
                    for (String symbol : symbols) {
                        DFAState target = null;
                        if (dfa.transitions.containsKey(state) && dfa.transitions.get(state).containsKey(symbol)) {
                            target = dfa.transitions.get(state).get(symbol);
                        }

                        // 找到目标状态所在的分区
                        int targetPartitionIndex = -1;
                        if (target != null) {
                            for (int i = 0; i < partitions.size(); i++) {
                                if (partitions.get(i).contains(target)) {
                                    targetPartitionIndex = i;
                                    break;
                                }
                            }
                        }
                        signature.append(symbol).append(":").append(targetPartitionIndex).append(";");
                    }

                    String sig = signature.toString();
                    separationMap.computeIfAbsent(sig, k -> new HashSet<>()).add(state);
                }

                // 如果有多个不同的签名，说明需要分割
                if (separationMap.size() > 1) {
                    changed = true;
                    newPartitions.addAll(separationMap.values());
                } else {
                    newPartitions.add(partition);
                }
            }

            partitions = newPartitions;
        }

        // 创建最小化的DFA
        DFA minDFA = new DFA();
        Map<Set<DFAState>, DFAState> partitionToStateMap = new HashMap<>();
        int stateIdCounter = 0;

        // 为每个分区创建一个新状态
        for (Set<DFAState> partition : partitions) {
            // 修复：将分区中的所有DFAState的nfaStates合并成一个Set<Integer>
            Set<Integer> nfaStates = partition.stream()
                    .flatMap(state -> state.nfaStates.stream())
                    .collect(Collectors.toSet());
            DFAState newState = new DFAState(stateIdCounter++, nfaStates);
            minDFA.states.add(newState);
            partitionToStateMap.put(partition, newState);

            // 检查是否是终态
            if (partition.stream().anyMatch(dfa.finalStates::contains)) {
                minDFA.finalStates.add(newState);
            }

            // 检查是否是初态
            if (partition.contains(dfa.startState)) {
                minDFA.startState = newState;
            }
        }

        // 建立转移函数
        for (Set<DFAState> partition : partitions) {
            DFAState newState = partitionToStateMap.get(partition);

            // 任选一个代表状态来确定转移
            DFAState representative = partition.iterator().next();

            if (dfa.transitions.containsKey(representative)) {
                for (Map.Entry<String, DFAState> transition : dfa.transitions.get(representative).entrySet()) {
                    String symbol = transition.getKey();
                    DFAState target = transition.getValue();

                    // 找到目标状态所在的分区
                    Set<DFAState> targetPartition = null;
                    for (Set<DFAState> p : partitions) {
                        if (p.contains(target)) {
                            targetPartition = p;
                            break;
                        }
                    }

                    if (targetPartition != null) {
                        DFAState newTarget = partitionToStateMap.get(targetPartition);
                        minDFA.transitions.computeIfAbsent(newState, k -> new HashMap<>()).put(symbol, newTarget);
                    }
                }
            }
        }

        return minDFA;
    }

    // DFA状态类
    static class DFAState {
        int id;
        Set<Integer> nfaStates;
        Map<String, DFAState> transitions;

        DFAState(int id, Set<Integer> nfaStates) {
            this.id = id;
            this.nfaStates = nfaStates;
            this.transitions = new HashMap<>();
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) return true;
            if (obj == null || getClass() != obj.getClass()) return false;
            DFAState dfaState = (DFAState) obj;
            return id == dfaState.id;
        }

        @Override
        public int hashCode() {
            return Integer.hashCode(id);
        }
    }

    // DFA内部类
    static class DFA {
        DFAState startState;
        Set<DFAState> states = new HashSet<>();
        Set<DFAState> finalStates = new HashSet<>();
        Map<DFAState, Map<String, DFAState>> transitions;

        DFA() {
            this.transitions = new HashMap<>();
        }
    }

    //检查正则表达式
    private void CheckRegularExpression(){
        String regularExpression = textField.getText();
        if(regularExpression.isEmpty()){
            JOptionPane.showMessageDialog(null,"请输入正规式！");
            return;
        }
        try {
            Pattern.compile(regularExpression);
            JOptionPane.showMessageDialog(null, "验证通过，可继续分析");
            this.textField.setEnabled(false);
            button_run.setEnabled(true);
            button_check.setEnabled(false);
        } catch (Exception e) {
            JOptionPane.showMessageDialog(null, "请输入正确的正规式！");
        }
    }

    //刷新重载
    void Fresh(){
        this.textField.setText("");
        this.leftTA.setText("");
        this.midTA.setText("");
        this.rightTA.setText("");
        this.PagePanel.removeAll();
        this.CreateUI();
    }

    private void createMenuBar() {
        MenuBar = new JMenuBar();
        // 设置菜单栏字体
        Font menuFont = new Font("Microsoft YaHei", Font.PLAIN, 16);
        MenuBar.setFont(menuFont);

        // 文件菜单
        JMenu fileMenu = new JMenu("文件");
        fileMenu.setFont(menuFont);
        MenuBar.add(fileMenu);

        JMenuItem fileMenu_open = new JMenuItem("打开");
        fileMenu_open.setFont(menuFont);
        fileMenu.add(fileMenu_open);

        JMenuItem fileMenu_save = new JMenuItem("保存");
        fileMenu_save.setFont(menuFont);
        fileMenu.add(fileMenu_save);

        // 编辑菜单
        JMenu editMenu = new JMenu("编辑");
        editMenu.setFont(menuFont);
        MenuBar.add(editMenu);

        JMenuItem editMenu_cut = new JMenuItem("剪切");
        editMenu_cut.setFont(menuFont);
        editMenu.add(editMenu_cut);

        JMenuItem editMenu_copy = new JMenuItem("复制");
        editMenu_copy.setFont(menuFont);
        editMenu.add(editMenu_copy);

        JMenuItem editMenu_paste = new JMenuItem("粘贴");
        editMenu_paste.setFont(menuFont);
        editMenu.add(editMenu_paste);
    }

    public JPanel SwitchNormalGrammar(){
        return this.PagePanel;
    }
    public JMenuBar GetNormalGrammarMenuBar(){
        return this.MenuBar;
    }

    // 保存状态转移表到文件
    private void saveTransitionTable(String content, String title) {
        if (content == null || content.trim().isEmpty()) {
            JOptionPane.showMessageDialog(PagePanel, "没有内容可保存！", "提示", JOptionPane.WARNING_MESSAGE);
            return;
        }

        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setDialogTitle("保存" + title);
        fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);

        // 设置默认文件名
        String defaultFileName = title + ".txt";
        fileChooser.setSelectedFile(new File(defaultFileName));

        int result = fileChooser.showSaveDialog(null);
        if (result == JFileChooser.APPROVE_OPTION) {
            File file = fileChooser.getSelectedFile();

            // 确保文件有.txt扩展名
            if (!file.getName().endsWith(".txt")) {
                file = new File(file.getAbsolutePath() + ".txt");
            }

            try (java.io.FileWriter writer = new java.io.FileWriter(file)) {
                writer.write(title + "\n");
                writer.write("========================\n");
                writer.write(content);
                JOptionPane.showMessageDialog(PagePanel, title + "保存成功！", "提示", JOptionPane.INFORMATION_MESSAGE);
            } catch (IOException ex) {
                JOptionPane.showMessageDialog(PagePanel, title + "保存失败: " + ex.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
            }
        }
    }

    // NFA内部类
    static class NFA {
        int startState = -1;
        Set<Integer> finalStates = new HashSet<>();
        List<Transition> transitions = new ArrayList<>();

        static class Transition {
            int from;
            String symbol;
            int to;

            Transition(int from, String symbol, int to) {
                this.from = from;
                this.symbol = symbol;
                this.to = to;
            }
        }
    }
}
